package com.yunc.base.security.filter;

import cn.hutool.json.JSONUtil;
import com.yunc.base.aspect.AuthIgnore;
import com.yunc.base.exception.UCException;
import com.yunc.base.utils.JwtApiTokenUtils;
import com.yunc.base.utils.R;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.MalformedJwtException;
import io.jsonwebtoken.SignatureException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * API token权限校验
 *
 * @author taocongcong
 * @create 2019-11-06 14:13
 */
@Component
public class JWTAuthorizationInterceptor extends HandlerInterceptorAdapter {

    private static final String TOKEN = "token";

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 验证有无注解
        AuthIgnore authIgnore;
        if (handler instanceof HandlerMethod) {
            authIgnore = ((HandlerMethod)handler).getMethodAnnotation(AuthIgnore.class);
        } else {
            return true;
        }
        if (authIgnore != null){
            return true;
        }
        // 业务处理,从header中获取token
        String token = request.getHeader(TOKEN);
        if (StringUtils.isBlank(token)) {
            token = request.getParameter(TOKEN);
        }
        // token不能为空
        if (StringUtils.isBlank(token)){
            throw new UCException("token不能为空");
        }
        try {
            JwtApiTokenUtils.isExpiration(token);
        } catch (MalformedJwtException e) {
            // 无法解析
            response.getWriter().write(JSONUtil.toJsonStr(R.error(HttpServletResponse.SC_FORBIDDEN, "Token format error")));
            return false;
        } catch (ExpiredJwtException e) {
            // token过期
            response.getWriter().write(JSONUtil.toJsonStr(R.error(HttpServletResponse.SC_FORBIDDEN, "Token expired")));
            return false;
        } catch (SignatureException e) {
            // 签名错误
            response.getWriter().write(JSONUtil.toJsonStr(R.error(HttpServletResponse.SC_FORBIDDEN, "Token format error")));
            return false;
        }
        // 保存到当前线程，那么就直接能获取到值
        JwtApiTokenUtils.setToken(token);
        return true;
    }

}
